package com.vgemv.jsutilitysdk.Request.JsRequestManager2.JsRequestExecutor;

import android.content.Context;
import android.util.Log;

import com.google.gson.reflect.TypeToken;
import com.vgemv.jsutilitysdk.JsJsonManager.JsJsonManager;
import com.vgemv.jsutilitysdk.JsThread.JsThreadManager;
import com.vgemv.jsutilitysdk.Request.JsRequestManager2.JsCookieOpCallback;
import com.vgemv.jsutilitysdk.Request.JsRequestManager2.JsRequestBaseData.IJsResponseHandler;
import com.vgemv.jsutilitysdk.Request.JsRequestManager2.JsRequestConfig;

import org.jetbrains.annotations.NotNull;

import java.io.IOException;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;

import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.Cookie;
import okhttp3.CookieJar;
import okhttp3.FormBody;
import okhttp3.HttpUrl;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
import okhttp3.ResponseBody;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.vgemv.jsutilitysdk.Request.JsRequestManager2.JsRequestInfo;
import com.vgemv.jsutilitysdk.SharedPreference.JsSharedPreferencesManager;

/**
 * 使用okhttp的处理.
 */
public class JsRequestExecutorOh {

    private OkHttpClient mDefaultClient;
    //用来存储cookie的map. 这样只能存储在内存中,第二次进入就没了.
    private HashMap<String, List<Cookie>> mMap_cookieStore = new HashMap<>();

    public JsCookieOpCallback mCookieOpCallback;

    public boolean mb_isSaveCookieToEp = true;
    private Gson mGson_sharedJsonParser =  new GsonBuilder().registerTypeAdapter(new TypeToken<Map<String, Object>>() {
    }.getType(), new JsJsonManager.MapTypeAdapter()).create();

    public void invokeRequest(JsRequestConfig config, IJsResponseHandler handler) {
        Object requestParam = config.requestBodyInput;
        switch (config.requestBodyInputType) {
            case MapToJson:{
                String param = mGson_sharedJsonParser.toJson(requestParam);
                post_json(config,(String)param,handler);
                break;
            }
            case Json: {
                post_json(config,(String)requestParam,handler);
                break;
            }
            default:{
                Log.e("JsRequestExecutorOh","not supported request");
            }
        }
    }

    //2 Post
    //2.1 post application/json
    //2.1.1 post application/json map参数 异步
//    //异步请求
//    public void postReqeustByJson(String url, Map map_param, final JsRequestDictionaryCallback dictionaryCallback) {
//
//        JsRequestStringCallback cb = new JsRequestStringCallback() {
//            @Override
//            public void onRequestResponse(final int responseCode, String resultObject, final String detailInfo) {
////                Map resultMap = mGson_sharedJsonParser.fromJson(result,Map.class);
////                Map resultMap = mGson_sharedJsonParser.fromJson(result,new TypeToken<TreeMap<String, Object>>(){}.getType());
//                final Map resultMap = mGson_sharedJsonParser.fromJson(resultObject, new TypeToken<Map<String, Object>>() {
//                }.getType());
//
//                //返回到主线程.
//                dictionaryCallback.onRequestResponse(responseCode, resultMap, detailInfo);
//            }
//        };
//        post_json(url, str_param, cb);
//    }





    private OkHttpClient defaultClient() {
        if(mDefaultClient == null) {
            OkHttpClient.Builder builder = new OkHttpClient.Builder();

            //1/4 自动存储cookie
            /**
             * 估计每一次请求,都会进行处理,将该url对应的host和cookies存起来到这个map中.
             * 然后每次发起请求时,都会先去查询是否有cookie,有的话就添加到header中.
             */
            builder.cookieJar(new CookieJar() {

                @Override
                //UnmodifiableRandomAccessList. 不可修改.
                public void saveFromResponse(HttpUrl url, List<Cookie> cookies) {
                    if(mCookieOpCallback != null) {
                        mCookieOpCallback.onSetCookie(url,cookies);
                    }
                }
                //!= null ? cookies : new ArrayList<Cookie>();
                @Override
                public List<Cookie> loadForRequest(HttpUrl url) {
                    if(mCookieOpCallback != null) {
                        List<Cookie> cookies = (List<Cookie>)mCookieOpCallback.onGetCookie(url);
                        if(cookies == null) {
                            //为空时必须传一个数组对象,否则会报错.
                            cookies =  new ArrayList<Cookie>();
                        }
                        return cookies;
                    }
                    return null;
                }
            });

            //2/4 允许https证书无效
            // Create a trust manager that does not validate certificate chains
            X509TrustManager x509TrustManager =  new X509TrustManager() {
                @Override
                public void checkClientTrusted(java.security.cert.X509Certificate[] chain, String authType) {
                }

                @Override
                public void checkServerTrusted(java.security.cert.X509Certificate[] chain, String authType) {
                }

                @Override
                public java.security.cert.X509Certificate[] getAcceptedIssuers() {
                    return new java.security.cert.X509Certificate[]{};
                }
            };
            final TrustManager[] trustAllCerts = new TrustManager[]{
                    x509TrustManager
            };

            // Install the all-trusting trust manager
            SSLContext sslContext = null;
            try {
                sslContext = SSLContext.getInstance("SSL");
                sslContext.init(null, trustAllCerts, new java.security.SecureRandom());
            }
            catch (Exception e) {
                e.printStackTrace();
            }
            // Create an ssl socket factory with our all-trusting manager
            final SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();

            builder.sslSocketFactory(sslSocketFactory,x509TrustManager);
            builder.hostnameVerifier(new HostnameVerifier() {
                @Override
                public boolean verify(String hostname, SSLSession session) {
                    return true;
                }
            });

            // 3/4 基本设置
            //连接超时时间
            builder.connectTimeout(10, TimeUnit.SECONDS);
            //设置读取超时时间
            builder.readTimeout(20, TimeUnit.SECONDS);



            // 4/4 允许http访问
            //3次重试
//            builder.addInterceptor(new JsRequestManager.RetryIntercepter(3));


            mDefaultClient = builder.build();


        }
        return mDefaultClient;
    }

    public void post_json(final JsRequestConfig config, final String requestJson, final IJsResponseHandler handler) {
        //1 创建请求
        //MediaType  设置Content-Type 标头中包含的媒体类型值
        RequestBody requestBody = FormBody.create(MediaType.parse("application/json; charset=utf-8")
                , requestJson);
        String requestUrlString = config.getRequestUrlString();
        final Request reqeust = new Request.Builder().url(requestUrlString).method("POST",requestBody).build();

        //2 创建客户端
        OkHttpClient client = defaultClient();

        JsRequestInfo info = new JsRequestInfo();
        info.requestUrlString = requestUrlString;

        //3 请求
        client.newCall(reqeust).enqueue(new Callback() {
            @Override
            public void onFailure(@NotNull Call call, @NotNull IOException e) {
                e.printStackTrace();
                Log.d("JsRequest","error");
                //系统级别的错误.
                JsThreadManager.runInMainThread(0, true, new Runnable() {
                    @Override
                    public void run() {
                        int rensponseState = -1;
                        info.responseStatus = info.responseStatus;;
                        handler.onResponse(rensponseState,null,"系统错误",info);
                    }
                });
            }

            @Override
            public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {
                ResponseBody body = response.body();
                final int responseCode = response.code();

                Object resultObject = null;
                //返回数据,根据请求中配置的格式进行转换.

                switch(config.responseBodyOutputType) {
                    case String:{
                        resultObject = body.string();
                        break;
                    }
                    case Data: {
                        resultObject = body.bytes();
                        break;
                    }
                    case JsonToMap:{
                        String json = body.string();
                        final Map resultMap = mGson_sharedJsonParser.fromJson(json,new TypeToken<Map<String, Object>>(){}.getType());
                        resultObject = resultMap;
                        break;
                    }
                    default:{

                    }
                }

                Object finalResultObject = resultObject;
                JsThreadManager.runInMainThread(0, true, new Runnable() {
                    @Override
                    public void run() {
                        handler.onResponse(responseCode, finalResultObject,null,info);
                    }
                });
            }
        });
    }


    public void postRequest(String url,Object object,final IJsResponseHandler handler) {

    }
}
